<template>
    <view ref="tm-dragList" class="tm-dragList flex flex-col flex-col-center-center">
        <view :style="{ height: h * list.length + 'px', width: w + 'px' }" class="relative flex flex-col"
            :class="[disabled ? 'opacity-4' : '']">
            <view class="overflow flex flex-col" :class="[
            'absolute',
            'tm-dragList-item', 'flex-between',
            ]" 
            v-for="(item, index) in listData" :key="index" :style="[
            {
                top: `${item.top}px`,
                height: h + 'px', width: w + 'px', zIndex: nowMove_index == index ? 5 : 0
            },
            isNvue?{'transition-delay': '0.1s'}:{'transition-duration': nowMove_index == index || endDrage ? '0s' : '0.25s'},
            ]">
                <tm-sheet hover-class="opacity-6" :border="1" border-direction="bottom" :color="nowMove_index == index ? 'grey-3' : 'white'"
                    _class="flex-1 flex flex-row flex-between" class="flex-1" :margin="[0, 0]" :padding="[0, 0]">
                    <view class=" flex flex-row flex-row-center-start pl-12" :style="{ height: (h - 1) + 'px' }">
                        <view v-if="item['icon']" class="flex-shrink fulled-height flex-center">
                            <tm-icon :color="item['color']" :name="item['icon']" :fontSize="40"></tm-icon>
                        </view>
                        <tm-text _class=" pl-24" :font-size="30" :label="item.text"></tm-text>
                    </view>
                    <view :style="{ height: (h - 1) + 'px', width: '100rpx' }" @touchstart.stop.prevent="m_start($event, index)"
                        @longpress="m_start_longpress(index)"  @mousedown="m_start($event, index)"
                        @touchmove.stop.prevent="m_move($event, index)" @mousemove.stop.prevent="m_move($event, index)"
                        @touchend="m_end($event, index)" @mouseup="m_end($event, index)"
                        class="flex-shrink flex flex-row flex-row-center-center opacity-3">
                        <tm-icon   :userInteractionEnabled="false" name="tmicon-menu"></tm-icon>
                    </view>
                </tm-sheet>
            </view>
        </view>
    </view>
</template>

<script lang="ts" setup>
/**
 * 拖放排序列表
 * @description 在h5和pc端，点击右边区域即可触发拖动。在MP和APP端需要长按右边区域触发拖动排序。
 * @description 已知hack:在nvue端，因zIndex不起作用，导致前端组件移动时，可能会被后面渲染的列表覆盖，但不影响使用，只影响些许美观。
 */
import { Ref, ref, nextTick, toRaw, onMounted, getCurrentInstance, PropType } from "vue";
import tmIcon from "../tm-icon/tm-icon.vue";
import tmSheet from "../tm-sheet/tm-sheet.vue";
import tmText from "../tm-text/tm-text.vue";
import { itemList } from "./interface";
const props = defineProps({
    disabled: {
        type: [String, Boolean],
        default: false
    },
    width: {
        type: Number,
        default: 700
    },
    height: {
        type: Number,
        default: 90
    },
    list: {
        type: Array as PropType<Array<itemList>>,
        default: () => {
            return []
        }
    },
    rangKey: {
        type: String,
        default: 'text'
    },
    rightIcon: {
        type: String,
        default: "icon-menu"
    },
    bgColor: {
        type: String,
        default: "white"
    },
})
const emits = defineEmits(["change"])
const w = ref(0);
const h = ref(0);
const totalH = ref(0);
let y = 0;
const new_index: Ref<number> = ref(NaN);//即将被替换的索引（实质性被替换）
const nowMove_index: Ref<number> = ref(NaN);//现在正在移动的索引
const listData = ref([])
let new_item = [];//虚拟列表，内部排列好，但未在页面中渲染。
const endDrage = ref(false);
const isNvue = ref(false)
// #ifdef APP-NVUE
isNvue.value = true;
// #endif
// tm-dragList
onMounted(() => jishunTopData())

function jishunTopData() {
    nextTick(function () {
        listData.value = [];
        w.value = uni.upx2px(props.width) || 700;
        h.value = uni.upx2px(props.height) || 120
        totalH.value = h.value * props.list.length
        let list = [];
        for (let i = 0; i < props.list.length; i++) {
            let p:itemList = props.list[i];
            p['top'] = i * h.value;
            p['i'] = i;
            p['__id'] = uni.$tm.u.getUid();
            listData.value.push(p)
        }
        new_item = [...listData.value];
    })
}
function m_start_longpress(index:number) {
    endDrage.value = false;
    nowMove_index.value = index;
    // #ifdef APP-NVUE
    uni.vibrateShort({
	success: function () {
        }
    })
    // #endif
    
}

function m_start(event:Event, index:number) { 
    
    event.preventDefault()
    event.stopPropagation()
    if (props.disabled) return;
    // #ifndef APP-NVUE
    endDrage.value = false;
    nowMove_index.value = index;
    // #endif
	
	
    new_item = [...listData.value];
    if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
        var touch = event.changedTouches[0];
        y = touch.pageY - event.currentTarget.offsetTop - listData.value[index].top
    } else {

        y = event.pageY - event.currentTarget.offsetTop - listData.value[index].top
    }

    // #ifdef APP-NVUE || MP
    // uni.vibrateShort()
    // #endif

}
function m_move(event:Event, index:number) {
    if (props.disabled) return;
    event.preventDefault()
    event.stopPropagation()

    if (isNaN(nowMove_index.value)) return;
    //当前元素的top位置。
    let ch = 0;
    if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
        var touch = event.changedTouches[0];
        ch = touch.pageY - y

    } else {
        ch = event.pageY - y
    }

    listData.value.splice(index, 1, {
        ...listData.value[index],
        top: ch
    })
    const currenit_index = index;
    const currentSort = listData.value[currenit_index].i;
    const currenit_id = listData.value[currenit_index].__id;

    // 计算当前移动的index.
    let moveIndex = Math.round(ch / h.value);

    moveIndex = moveIndex < 0 ? 0 : moveIndex;
    moveIndex = moveIndex > listData.value.length - 1 ? listData.value.length - 1 : moveIndex;

    moveIndex = Math.abs(moveIndex)

    index = moveIndex;
    let elList = [...listData.value]
    for (let i = 0; i < elList.length; i++) {
        if (currentSort < moveIndex) {
            if (elList[i].i > currentSort && elList[i].i <= moveIndex) {
                elList[i].i -= 1;
            };
        } else if (currentSort > moveIndex) {
            if (elList[i].i < currentSort && elList[i].i >= moveIndex) {
                elList[i].i += 1;
            };
        }
    };
    elList[currenit_index].i = moveIndex;
    elList = elList.map(im => {
        if (im.__id != currenit_id) {
            im.top = im.i * h.value;
        }

        return im;
    })
    listData.value = elList;
    new_index.value = moveIndex;



}
function m_end(event:Event, index:number) {
    if (props.disabled) return;
    event.preventDefault()
    event.stopPropagation()
    nowMove_index.value = NaN;
    endDrage.value = true;
    if (isNaN(new_index.value)) return;
    let elList = [...listData.value]
    elList = elList.map(im => {
        im.top = im.i * h.value;
        return im;
    })
    elList.sort((a, b) => a.i - b.i)
    listData.value = [...elList]
    moveChange();
}

function moveChange() {
    if (props.disabled) return;
    //change后修改的数据 。
    emits('change', toRaw(listData.value));
}
</script>

<style scoped>
.tm-dragList-item {
    transition-delay: 0s;
    transition-property: top,left,transform;
    transition-timing-function: ease;
    transition-duration: 0.15s;
}
</style>